无法同时开启springboot和netty服务器端口的监听,和netty整合使用mybatis的问题 (后附完整的springboot整合netty代码) 您所在的位置:网站首页 springboot websocket端口修改 无法同时开启springboot和netty服务器端口的监听,和netty整合使用mybatis的问题 (后附完整的springboot整合netty代码)

无法同时开启springboot和netty服务器端口的监听,和netty整合使用mybatis的问题 (后附完整的springboot整合netty代码)

2024-01-18 10:38| 来源: 网络整理| 查看: 265

目的背景描述解决办法SpringBoot整合Netty完整代码 目的

 解决springboot程序监听的端口和netty服务监听的端口无法同时开启的问题,以及netty无法较为便利地使用mybatis操作数据库的问题。

背景描述

 正在做的一个IM即时通讯项目,springboot服务器负责监听http的CRUD等请求,netty的websocket服务器负责即时聊天消息的签收和推送功能。常见的两种springboot整合netty的方法如下:

 1、单独写一个main方法,运行netty server,这样的话需要启动两次,分别启动springboot和netty server启动类,而且此时netty server没办法使用spring容器中的bean用mybatis进行CRUD,只能使用JDBC来操作数据库。

 2、在netty server的启动方法上面使用 @PostConstruct 的注解,在bean的依赖注入完成后会自动执行该注解标注的方法,同时netty server类和相关handler类上也需要标注 @component 和 handler类上的 @Sharable注解。

 但此时启动springboot,netty服务能正常启动并监听websocket端口,netty server也能正常注入spring容器中的bean,可是springboot监听的端口会被覆盖,无法访问。

@Component public class WebSockerServer { @PostConstruct public void runNettyServer() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); //...... } } @Component @Sharable public class NettyChannelInitializer extends ChannelInitializer { @Autowired private ChatChannelHandler chatChannelHandler; }

解决方法

 1、netty server类实现Runnable接口,重写run( ) 方法,在run( ) 方法内部启动netty server。

@Component("WebSocketServer") public class WebSockerServer implements Runnable { @Autowired private NettyChannelInitializer nettyChannelInitializer; @Override public void run() { EventLoopGroup bossGroup = new NioEventLoopGroup(); ...... } }

  2、在springboot启动类中从spring容器中获取netty server的bean,创建线程池然后执行execute( )方法开启netty server线程。

@EnableOpenApi @SpringBootApplication @MapperScan("com.duke.chatapp.dao") public class ChatappApplication { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(ChatappApplication.class, args); WebSockerServer webSockerServer = ctx.getBean("WebSocketServer", WebSockerServer.class); ExecutorService service = Executors.newCachedThreadPool(); service.execute(webSockerServer); service.shutdown(); } }

Springboot整合Netty完整代码

1、在pom.xml中添加netty依赖

4.1.57.Final io.netty netty-all ${netty.version}

2、netty server类的编写

@Component("WebSocketServer") public class WebSockerServer implements Runnable { @Autowired private NettyChannelInitializer nettyChannelInitializer; @Override public void run() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap server = new ServerBootstrap(); server.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(nettyChannelInitializer) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture future = server.bind(8889).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }

3、channel初始化类的编写

@Component @Sharable public class NettyChannelInitializer extends ChannelInitializer { @Autowired private ChatChannelHandler chatChannelHandler; @Override protected void initChannel(SocketChannel channel) throws Exception { //获取管道 ChannelPipeline pipeline = channel.pipeline(); //添加http编解码器 pipeline.addLast(new HttpServerCodec()); //对写大数据流进行支持 pipeline.addLast(new ChunkedWriteHandler()); //对httpMessage进行聚合处理 pipeline.addLast(new HttpObjectAggregator(1024 * 64)); //处理握手动作 pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); pipeline.addLast(chatChannelHandler); } }

4、channel handler类的编写

@Component @Sharable public class ChatChannelHandler extends SimpleChannelInboundHandler { private static final Map users = new ConcurrentHashMap(); @Autowired private MessageService messageService; @Override protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg){ String msgStr = msg.text(); System.out.println(msgStr); MessagePack messagePack = JsonUtil.Json2Pojo(msgStr, MessagePack.class); //业务代码... ... } @Override public void handlerAdded(ChannelHandlerContext ctx) { System.out.println(ctx.channel().id().asShortText() + " : 注册"); } @Override public void handlerRemoved(ChannelHandlerContext ctx) { System.out.println(ctx.channel().id().asShortText() + " : 退出注册"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { System.out.println(cause.getMessage()); } }

5、springboot启动类的编写

@EnableOpenApi @SpringBootApplication @MapperScan("com.duke.chatapp.dao") public class ChatappApplication { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(ChatappApplication.class, args); WebSockerServer webSockerServer = ctx.getBean("WebSocketServer", WebSockerServer.class); ExecutorService service = Executors.newCachedThreadPool(); service.execute(webSockerServer); service.shutdown(); } }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有